http://realm.io.s3-website-us-east-1.amazonaws.com/assets/downloads/NSPredicateCheatsheet.pdf

1. 创建Predicates

1.1 使用Format String创建predicate (最常用)

 let predicate = NSPredicate(format: "(lastName like[cd] %@) AND (birthday > %@)", lastNameSearchString, birthdaySearchDate)
其中[c]代表大小写不敏感case-insensitive, [d]代表可以搜索同音词diacritic-insensitive

在我们创建predicate 语句时，关键词大小写均可

1.2 字符串、变量、通配符

当我们在predicate中使用到字符串的时，必须使用引号将字符串包裹起来, 单引号双引号都可以使用，但是必须成对使用

 let predicate = NSPredicate(format: "lastName like[c] \"S*\"") //双引号
 let predicate = NSPredicate(format: "lastName like[c] \'S*\'") //单引号
如果我们使用变量替换（自动引用）%@ ，predicate 会自动为我们添加引号

let predicate = NSPredicate(format: "lastName like[c] %@", "S*")
在我们使用通配符的时候，必须使用自动引用,并且在引用之前就添加好通配符

let prefix = "prefix"
let suffix = "suffix"
let predicate = NSPredicate(format: "SELF like[c] %@", "\(prefix)*\(suffix)")
print(predicate.evaluate(with: "prefixxxxxxsuffix"))  //true
如果我们按照下面这种形式写语句，会造成程序崩溃

let prefix = "prefix"
let suffix = "suffix"
let predicate = NSPredicate(format: "SELF like[c] %@*%@", prefix, suffix)
print(predicate.evaluate(with: "prefixxxxxxsuffix")) //error
1.3 动态属性名

由于使用%@将变量替换为字符串时，字符串会加上引号，因此不能使用%@指定动态属性名,我们需要使用%K来将变量设为属性名

let predicate = NSPredicate(format: "%K like %@", "attributeName", "attributeValue")
1.4 使用模板创建Predicates

// 创建模板
let predicateTemplate = NSPredicate(format: "lastName like[c] $LAST_NAME")
// 根据模板创建predicate
let predicate = predicateTemplate.withSubstitutionVariables(["LAST_NAME": "Turner"])
print(predicate)

2. 使用Predicates

2.1 Evaluating Predicates

let predicate = NSPredicate(format: "SELF IN %@", ["1", "2", "3"])
let result = predicate.evaluate(with: "1")
print(result)
2.2 Predicate中Key-Paths的使用

我们可以在 NSPredicate中使用key path

let departmentName = ""
3let predicate = NSPredicate(format: "department.name like %@", departmentName)
2.3 Using Null Values

如果我们想匹配null,需要在语句里写出

let predicate = NSPredicate(format: "(firstName == %@) || (firstName = nil)", "firstName")
3. Predicate语法

3.1. Parser Basics

NSPredicate字符串解析器对于关键字不区分空格和大小写，支持嵌套的括号表达式。解析器不支持语义类型检查。

变量使用$关键字，例如$VARIABLE_NAME。 ?不是有效的关键字

格式字符串支持printf风格的格式说明符，例如%x。两个重要的格式说明符是%@和%K。

%@ 一般是替换为string, number, or date.
%K keyPath.
使用%@替换表达式。不要用它来表示整个谓词，不然系统会报错
3.2 基本比较符号

=,== 相等

>=,=> 大于等于

<=,=< 小于等于

> 大于

< 小于

!=,<> 不等于

BETWEEN 左边的表达式值在右边表达式范围中（包括相等）

let betweenPredicate = NSPredicate(format: "self BETWEEN %@", [1, 10])
print(betweenPredicate.evaluate(with: 10))
3.3 复合符号

AND,&& 逻辑与

OR,|| 逻辑或

NOT,! 逻辑非

3.4 字符串比较

字符串比较默认是大小写敏感的，我们可以使用修饰符[cd] 来设置大小写及音符不敏感

firstName BEGINSWITH[cd] $FIRST_NAME
BEGINSWITH 以..开头

CONTAINS 包含

ENDSWITH 以..结尾

LIKE 通配符?匹配1个字符，*匹配0个或更多字符

MATCHES 正则表达式匹配

3.5 聚合

ANY,SOME

ANY children.age < 18
ALL

ALL children.age < 18
NONE

NONE children.age < 18
IN

name IN { 'Ben', 'Melissa', 'Nick' }
